﻿using System;
using System.Collections.Generic;
using Foxit.PDF;
using Foxit.PDF.IO;
using Foxit.PDF.PageElements;
using Sustainalytics.Entities.RiskRatings;
using Sustainalytics.Reporting.Framework;

namespace Sustainalytics.RiskRatings.Reporting
{
    public class RiskRating_CustomBulletChart : PageElement
    {
        public float Left { get; set; }
        public float Top { get; set; }
        public string Assessment { get; set; }
        public double Value { get; set; }
        public float Width { get; set; }
        public float Height { get; set; }
        public List<RiskRatingCluster> RiskRatingClusterList { get; set; }
        public float BarHeight { get; set; }

        private Group Elements()
        {
            var elements = new Group();

            float currentYOffset = Top;
            float startingPos;

            Dictionary<string, RgbColor> assessmentColors = new Dictionary<string, RgbColor>()
            {
                {"X", RgbColor.LightGrey }, // new RgbColor(252, 238, 204)},
                {"A",  new RgbColor(249, 221, 153)},
                {"B",  new RgbColor(246, 205, 102)},
                {"C",  new RgbColor(243, 188, 51)},
                {"D",  new RgbColor(240, 171, 0)}
            };

            //the value
            var clusterType = RiskRatingClusterList[0].Type;
            var maxScoreText = clusterType == RiskRatingClusterType.Overall ? "/100" : "/20+";

            float NumberWidth = Fonts.RobotoRegular.GetTextWidth(Value.ToString("0.0"), 20.5f);

            elements.Add(new Label(Value.ToString("0.0"), Left, currentYOffset, NumberWidth, 22.5f, Fonts.RobotoRegular, 20.5f, TextAlign.Left, RgbColor.Black));
            elements.Add(new Label(maxScoreText, Left + NumberWidth + 5f, currentYOffset + 4.5f, 40f, 18f, Fonts.RobotoRegular, 16f, TextAlign.Left, RgbColor.Gray));
            if (!string.IsNullOrEmpty(Assessment))
                elements.Add(new Label(Assessment, Left + NumberWidth + 45f, currentYOffset + 4.5f, 200f, 18f, Fonts.RobotoRegular, 16f, TextAlign.Left, RgbColor.Black));

            currentYOffset += 30f;

            startingPos = Left;


            foreach (var cluster in RiskRatingClusterList)
            {
                if (Value >= cluster.UpperBound)
                {
                    elements.Add(new Rectangle(startingPos, currentYOffset, 50f, 12f,
                        assessmentColors[cluster.Code], assessmentColors[cluster.Code]));
                }
                else if (Value >= cluster.LowerBound && Value < cluster.UpperBound)
                {
                    elements.Add(new Rectangle(startingPos, currentYOffset, 50f, 12f,
                        //assessmentColors[cluster.Code], assessmentColors[cluster.Code]));
                        RgbColor.Black, assessmentColors[cluster.Code]));
                    startingPos += 1f;
                }
                else
                {
                    elements.Add(new Rectangle(startingPos, currentYOffset, 50f, 12f,
                       RgbColor.LightGrey, RgbColor.White, 0.5f));
                }

                if (cluster.Assessment.ToString() == Assessment)
                {
                    elements.Add(new Label(ConvertAssessment(cluster.Code, cluster.Assessment.ToString()),
                        startingPos,
                        currentYOffset + 3f,
                        48f,
                        7.5f, Fonts.RobotoBold, 5.5f, TextAlign.Center, RgbColor.Black));
                }
                else
                {
                    elements.Add(new Label(ConvertAssessment(cluster.Code, cluster.Assessment.ToString()),
                        startingPos,
                        currentYOffset + 3f,
                        50f,
                        7.5f, Fonts.RobotoRegular, 5.5f, TextAlign.Center, RgbColor.Black));
                }
                var plus = string.Empty;
                if ((cluster.UpperBound == 20 || cluster.UpperBound == 100) && clusterType==RiskRatingClusterType.MEI)
                {
                    cluster.UpperBound = 20;
                    plus = "+";
                }
                elements.Add(new Label($"{cluster.LowerBound}-{cluster.UpperBound}"+plus,
                    startingPos - 0.5f,
                    currentYOffset + 15f,
                    50f,
                    7.5f, Fonts.RobotoRegular, 5.5f, TextAlign.Center, RgbColor.Gray));

                startingPos += 50f;
            }

            startingPos = Left;
            var score = Math.Round(Value, 1);

            foreach (var cluster in RiskRatingClusterList)
            {
                if (cluster.UpperBound == 100 && clusterType == RiskRatingClusterType.MEI)
                {
                    cluster.UpperBound = 20;
                }
                var boundDiff = cluster.UpperBound - cluster.LowerBound;
                var scoreDiff = score - cluster.LowerBound;

                var unit = 50 / boundDiff;

                var increment = 0f;

                if (score > cluster.UpperBound)
                {
                    increment = (float)(unit * boundDiff);
                }
                else if (score > cluster.LowerBound && score <= cluster.UpperBound)
                {
                    increment = (float)(unit * scoreDiff);
                }

                startingPos += increment;
            }

            var path = new Path(startingPos, currentYOffset - 2f, RgbColor.Black, RgbColor.Black, 1, LineStyle.Solid, true);


            path.SubPaths.Add(new LineSubPath(startingPos - 3f, currentYOffset - 7f));
            path.SubPaths.Add(new LineSubPath(startingPos + 3f, currentYOffset - 7f));

            elements.Add(path);

            return elements;
        }

        private string ConvertAssessment(string code, string assessment)
        {
            return code == "X" ? assessment.Substring(0, 4) : code == "B" ? assessment.Substring(0, 3) : assessment;
        }

        public override void Draw(PageWriter writer)
        {
            var elements = Elements();
            writer.Write_q_(true);
            elements.Draw(writer);
            writer.Write_Q(true);
        }
    }
}
 
